<?php
namespace Modules\Admin\Controllers;

use Modules\Admin\Model\Data\Acl as DataAcl;
use Modules\Admin\Model\Service\Access\Control as ServiceAccessControl;
use Modules\Admin\Model\Service\Access\Config as ServiceAccessConfig;
use Base\Exception\Controller as Exception;
/**
 * @name 访问控制管理
 */
class Acl extends Controller {

    protected $sys_view = true;

	/**
	 * 列出所有控制器和方法，用于权限配置
	 *	包括：
	 *		1. user		- acl	用户
	 *		2. group	- acl	用户组
	 *		3. all		- acl	全局访问（默认deny）
	 *	user > group > all
	 *	deny > allow
	 *
	 * @name 权限控制列表
	 * @throws Exception
	 */
	public function indexAction() {
		//uid|gid|id
		$permission = $this->_getAclConf();

		//【角色】管理员和已冻结用户
		if ($permission['type'] == ServiceAccessConfig::ACL_UID) {
			if (ServiceAccessControl::isSetAcl($permission['id'])) {
                throw new Exception("error.admin.can_not_be_modified");
			}
		}

		$data = ServiceAccessControl::aclData($permission['type'], $permission['id']);

		$this->response['id'] = $permission['id'];
		$this->response['type'] = $permission['type'];
		$this->response['data'] = json_encode($data);
		$this->response['actions'] = ServiceAccessControl::getList();
	}


	/**
	 * @name 设置权限（添加/修改acl）
	 * @format json
	 * @throws Exception
	 */
	public function accessControlAction() {
		$data = $this->getParams('data');
		$node_data	= json_decode(stripcslashes($data), true);
		unset($data);
		if (empty($node_data)) {
            throw new Exception('error.admin.no_config_info');
		}

		$permission = $this->_getAclConf();
		$type	= $permission['type'];
		$id		= $permission['id'];
		//	处理由继承关系生成的全部访问数据
		$odata	= (array)ServiceAccessControl::aclData($type, $id, true);

		//controller和AccessControl访问权限相同时，只记录controller的（不记录都为空的）
		//controller和AccessControl访问权限不全相同时，记录controller和不同于action的
		$add = $del = array();
		//对比已存在的和提交的对比
		foreach ($node_data as $key=>$option) {
			//add
			if (!isset($odata[$key]) && $option !== '') {
				$add[]	= $this->_setData($key, $option, $permission);
			}
			//del
			if (isset($odata[$key]) && $option === '') {
				$del[]	= $this->_setData($key, $option, $permission);
			}
			//update
			if (isset($odata[$key]) && $option !== $odata[$key]) {
				if($option !== '') {
					$add[]	= $this->_setData($key, $option, $permission);
				}
				$del[]	= $this->_setData($key, $option, $permission);
			}
		}

		//	已经被删除的方法	-理论上应该全部相关方法的权限都删除，暂时只删被修改的
		$lost = array_diff(array_keys($odata), array_keys($node_data));
		if (!empty ($lost)) {
			foreach ($lost as $lost_info) {
				$del[]	= $this->_setData($lost_info, $odata[$lost_info], $permission);
			}
		}

		//更新内容
		if (!empty($del)) {
			$this->_acl('del', $type, $del);
		}
		if (!empty($add)) {
			$this->_acl('add', $type, $add);
		}
        $this->response['msg'] = '修改成功';
	}


	private function _setData($key, $option, $permission) {
		$tmp = explode('-', $key);
		//匹配正常类名和函数名
		if (empty($tmp[0]) || !$this->_nameCheck($tmp[0]) || (!empty($tmp[1]) && !$this->_nameCheck($tmp[1]))) {
			return array();
		}

		$ret = array(
			'controller' => $tmp[0],
			'action' => (string)$tmp[1],
			'option' => $option,
			$permission['type'] => $permission['id']
		);

		return $ret;
	}

	private function _nameCheck($name) {
		return preg_match('/[a-zA-Z0-9_]+/', $name);
	}

	/**
	 * 权限配置获取
	 * @return array
	 */
	private function _getAclConf() {

		if (isset($_REQUEST['uid'])) {			//用户权限配置
			$data = array(
				'type'	=> ServiceAccessConfig::ACL_UID,
				'id'	=> (int)$this->getParams('uid')
			);
		} else if (isset($_REQUEST['gid'])) {	//用户组权限配置
			$data = array(
				'type'	=> ServiceAccessConfig::ACL_GID,
				'id'	=> (int)$this->getParams('gid')
			);
		} else {								//全部权限配置
			$data = array(
				'type'	=> 'id',
				'id'	=> 0
			);
		}

		return $data;
	}

	private function _acl($option, $type, $data) {
		$map	= array('uid'=>'User', 'gid'=>'Group', 'id'=>'');
		$method	= $option.$map[$type].'Acl';
		$res =  (new DataAcl)->$method($data);
		return $res;
	}
}
